// 版权所有2016 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package crc32

import "internal/cpu"

const (
	vxMinLen    = 64
	vxAlignMask = 15 // 对齐到16字节
)

// hasVX报告机器是否安装并启用了z/体系结构
// 矢量工具。
var hasVX = cpu.S390X.HasVX

// vectoriazedcastagoni使用向量指令实现CRC32。
// 在crc32_s390x.s中定义。
// go:noescape 
func vectorizedCastagnoli(crc uint32, p []byte) uint32

// vectoriazediee使用向量指令实现CRC32。
// 在crc32_s390x.s中定义。
// go:noescape 
func vectorizedIEEE(crc uint32, p []byte) uint32

func archAvailableCastagnoli() bool {
	return hasVX
}

var archCastagnoliTable8 *slicing8Table

func archInitCastagnoli() {
	if !hasVX {
		panic("not available")
	}
	// 对于小型缓冲区，我们仍然使用8倍切片。
	archCastagnoliTable8 = slicingMakeTable(Castagnoli)
}

// ArchUpdateCastanoli使用
// /VectoriazedCastagoni计算p的校验和。
func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
	if !hasVX {
		panic("not available")
	}
	// 如果数据长度高于阈值，则使用矢量化函数。
	if len(p) >= vxMinLen {
		aligned := len(p) & ^vxAlignMask
		crc = vectorizedCastagnoli(crc, p[:aligned])
		p = p[aligned:]
	}
	if len(p) == 0 {
		return crc
	}
	return slicingUpdate(crc, archCastagnoliTable8, p)
}

func archAvailableIEEE() bool {
	return hasVX
}

var archIeeeTable8 *slicing8Table

func archInitIEEE() {
	if !hasVX {
		panic("not available")
	}
	// 对于小型缓冲区，我们仍然使用8倍切片。
	archIeeeTable8 = slicingMakeTable(IEEE)
}

// archupdateiee使用vectoriazediee计算p的校验和。
func archUpdateIEEE(crc uint32, p []byte) uint32 {
	if !hasVX {
		panic("not available")
	}
	// 如果数据长度高于阈值，则使用矢量化函数。
	if len(p) >= vxMinLen {
		aligned := len(p) & ^vxAlignMask
		crc = vectorizedIEEE(crc, p[:aligned])
		p = p[aligned:]
	}
	if len(p) == 0 {
		return crc
	}
	return slicingUpdate(crc, archIeeeTable8, p)
}
